/*
关于QueryBuilder 组件弹出层遮挡下发组件的处理方式：
<QueryBuilder target='.__push__008'>
</QueryBuilder>
<div className='__push__008'>
</div>
在QueryBuilder 上指定需要往下移动的元素的 <类名>__push__008
*/

import './QueryBar.scss';
import * as React from 'react';
import { Form } from 'antd';
import classnames from 'classnames';
import * as ReactDOM from 'react-dom';
import { setElementStyle } from './tool';
import { BindComponentMethodThis } from './decorators/BindComponentMethodThis';

const containerRefKey = 'query_builder';

interface IQueryBuilderProps {
  onSubmit?: Function;
  initSize?: string;
  target?: string;
}
interface IQueryBuilderStates {
  size: string;
}
class Base extends React.Component<any, any> {
  render() {
    const {children} = this.props;
    return (
      <div className='query-builder-base' data-base >
        {children}
      </div>
    );
  }
}
class Expand extends React.Component<any, any> {
  render() {
    const {children} = this.props;
    return (
      <div className='query-builder-expand' data-expand >
        {children}
      </div>
    );
  }
}

@BindComponentMethodThis()
export default class QueryBuilder extends React.Component<IQueryBuilderProps, IQueryBuilderStates> {
  static defaultProps = { initSize: 'base' };
  static Base = Base;
  static Expand = Expand;

  private target: HTMLElement = null;
  private baseElement: HTMLElement = null;
  private expandElement: HTMLElement = null;
  private btnElement: HTMLElement = null;
  private expandElementHeight = 0;

  public constructor(props: IQueryBuilderProps) {
    super(props);
    this.state = {
      size: props.initSize
    };
  }

  public calcBuilderExpandPosition() {
    this.target = ReactDOM.findDOMNode(this.refs[containerRefKey]) as HTMLElement;
    this.baseElement = this.target.querySelector('.query-builder-base') as HTMLElement;
    this.expandElement = this.target.querySelector('.query-builder-expand') as HTMLElement;
    this.btnElement = this.target.querySelector('.expand-trigger') as HTMLElement;
    // 加 25 像素
    this.expandElementHeight = this.expandElement.offsetHeight + 25;
  }

  public componentDidUpdate() {
    this.calcBuilderExpandPosition();
  }
  public componentDidMount() {
    this.calcBuilderExpandPosition();
  }
  public componentWillMount() {
    window.addEventListener('click', this.hideQueryBar);
  }
  public componentWillUnmount() {
    window.removeEventListener('click', this.hideQueryBar);
  }

  public showQueryBar() {
    // 更改需要触发推下去效果的Element的位置
    if (!this.target.classList.contains('expand')) {
      this.target.classList.add('expand');
    }
    setElementStyle(this.expandElement, { transform: `translateY(${this.baseElement.offsetHeight}px)` });
    changeTargetPosition(this.props.target, this.expandElementHeight);
    this.setState({ size: 'expand' });
  }

  public hideQueryBar() {
    this.target.classList.remove('expand');
    setElementStyle(this.expandElement, { transform: `translateY(${0}px)` });
    changeTargetPosition(this.props.target, 0);
    this.setState({ size: 'base' });
  }

  public onSubmit(evt: React.MouseEvent<any>) {
    if (this.props.onSubmit) {
      this.props.onSubmit();
    };
  }

  public onClick(evt: React.MouseEvent<any>) {
    let target = evt.target as HTMLElement;
    do {
      // 判断是否是需要展开expand
      if (target.hasAttribute('data-size-trigger')) {
        let newSize = this.state.size;
        if (newSize === 'base') {
          this.showQueryBar();
        } else {
          this.hideQueryBar();
        }
        break;
      }
    } while (target = target.parentElement);
    evt.stopPropagation();
    return false;
  }

  public render() {
    const {children} = this.props;
    const {size} = this.state;
    return (
      <div className={classnames('query-builder', { base: size === 'base', expand: size === 'expand' })}
        onClick={this.onClick}
        ref={containerRefKey}
      >
        <Form inline className='queryForm' onSubmit={this.onSubmit}>
          {children}
        </Form>
      </div>
    );
  }
}


function changeTargetPosition(target: string, position: number = 0) {
  if (target) {
    let targets = document.querySelectorAll(target);
    [...targets].forEach((target: HTMLElement) => {
      setElementStyle(target, {
        transition: '.5s all',
        transform: `translateY(${position}px)`
      });
    });
  }
}
